package com.tfswx.jcyw.sqlmodel.api.bean.table;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.Data;

import java.io.*;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 张述江
 * @date 2023/9/15
 */
@Data
public abstract class Select implements Expression, Cloneable {
    private Limit limit;

    private List<OrderByElement> orderByElements;

    private Alias alias;

    public abstract StringBuilder appendSelectBodyTo(StringBuilder builder);


    public StringBuilder appendTo(StringBuilder builder) {
        appendSelectBodyTo(builder);

        builder.append(orderByToString(orderByElements));

        return builder;
    }

    public static String orderByToString(List<OrderByElement> orderByElements) {
        return getFormattedList(orderByElements, "ORDER BY");
    }


    public static String getFormattedList(List<?> list, String expression) {
        return getFormattedList(list, expression, true, false);
    }

    public static String getFormattedList(List<?> list, String expression, boolean useComma, boolean useBrackets) {
        String sql = getStringList(list, useComma, useBrackets);

        if (!sql.isEmpty()) {
            if (!expression.isEmpty()) {
                sql = " " + expression + " " + sql;
            } else {
                sql = " " + sql;
            }
        }

        return sql;
    }

    @Override
    public String toString() {
        return appendTo(new StringBuilder()).toString();
    }

    public static String getStringList(List<?> list) {
        return getStringList(list, true, false);
    }

    public static String getStringList(List<?> list, boolean useComma, boolean useBrackets) {
        return appendStringListTo(new StringBuilder(), list, useComma, useBrackets).toString();
    }

    public static StringBuilder appendStringListTo(StringBuilder builder, List<?> list, boolean useComma, boolean useBrackets) {
        if (list != null) {
            String comma = useComma ? ", " : " ";

            if (useBrackets) {
                builder.append("(");
            }

            builder.append(list.stream().map(String::valueOf).collect(Collectors.joining(comma)));

            if (useBrackets) {
                builder.append(")");
            }
        }
        return builder;
    }

    public static String toJson(Select select) {
        return JSON.toJSONString(select, SerializerFeature.WriteClassName);
    }

    public static Select fromJson(String json) {
        return JSON.parseObject(json, Select.class, Feature.SupportAutoType);
    }
}
